﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections.Specialized;

namespace Qreed.IO
{
    /// <summary>
    /// Utility class for the IO namespace.
    /// </summary>
    public static class IOHelper
    {
        public static string GetCommonBaseFolder(string[] folders)
        {
            if (folders == null || folders.Length == 0)
                throw (new ArgumentException("folders"));

            List<string[]> foldersList = new List<string[]>();

            int minFolderCount = Int32.MaxValue;

            foreach (string folder in folders)
            {
                string[] arr = folder.Split(Path.DirectorySeparatorChar);
                minFolderCount = Math.Min(arr.Length, minFolderCount);

                foldersList.Add(arr);
            }

            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < minFolderCount; i++)
            {
                string currentFolder = foldersList[0][i];

                for (int j = 1; j < foldersList.Count; j++)
                {
                    if (string.Compare(foldersList[j][i], currentFolder, true) != 0)
                    {
                        currentFolder = null;
                        break;
                    }
                }

                if (currentFolder == null)
                    break;

                sb.Append(currentFolder);
                sb.Append(Path.DirectorySeparatorChar);
            }

            return sb.ToString();
        }

        /// <summary>
        /// Converts a relative path to an absolute path.
        /// </summary>
        /// <param name="basePath">The base path.</param>
        /// <param name="relativePath">The relative path.</param>
        /// <returns>The absolute path.</returns>
        public static string MakeAbsolutePath(string basePath, string relativePath)
        {
            if (string.IsNullOrEmpty(basePath))
                throw new ArgumentNullException("basePath");

            if (string.IsNullOrEmpty(relativePath))
                throw new ArgumentNullException("relativePath");

            if (Path.IsPathRooted(relativePath))
            {
                if (relativePath[0] == Path.DirectorySeparatorChar)
                {
                    relativePath = relativePath.TrimStart(new char[] { Path.DirectorySeparatorChar });
                    relativePath = Path.GetPathRoot(basePath) + relativePath;
                }

                return relativePath;
            }

            return Path.Combine(basePath, relativePath);
        }

        /// <summary>
        /// Creates a relative path.
        /// </summary>
        /// <param name="basePath">The base path.</param>
        /// <param name="targetPath">The target path.</param>
        /// <returns>The relative path</returns>
        public static string MakeRelativePath(string basePath, string targetPath)
        {
            if (string.IsNullOrEmpty(basePath))
                throw new ArgumentNullException("basePath");

            if (string.IsNullOrEmpty(targetPath))
                throw new ArgumentNullException("targetPath");

            bool isRooted = Path.IsPathRooted(basePath) && Path.IsPathRooted(targetPath);

            if (isRooted)
            {
                bool isDifferentRoot = string.Compare(Path.GetPathRoot(basePath),
                                                      Path.GetPathRoot(targetPath), true) != 0;

                if (isDifferentRoot)
                    return targetPath;
            }

            StringCollection relativePath = new StringCollection();

            string[] fromDirectories = basePath.Split(Path.DirectorySeparatorChar);
            string[] toDirectories = targetPath.Split(Path.DirectorySeparatorChar);

            int length = Math.Min(fromDirectories.Length, toDirectories.Length);
            int lastCommonRoot = -1;

            // find common root

            for (int x = 0; x < length; x++)
            {
                if (string.Compare(fromDirectories[x], toDirectories[x], true) != 0)
                    break;

                lastCommonRoot = x;
            }

            if (lastCommonRoot == -1)
                return targetPath;

            // add relative folders in from path
            for (int x = lastCommonRoot + 1; x < fromDirectories.Length; x++)
                if (fromDirectories[x].Length > 0)
                    relativePath.Add("..");

            // add to folders to path
            for (int x = lastCommonRoot + 1; x < toDirectories.Length; x++)
                relativePath.Add(toDirectories[x]);

            // create relative path
            string[] relativeParts = new string[relativePath.Count];

            relativePath.CopyTo(relativeParts, 0);
            string newPath = string.Join(Path.DirectorySeparatorChar.ToString(), relativeParts);

            return newPath;
        }
    }
}
